#ifndef POOL_H
#define POOL_H

#include "value.h"

typedef struct MBlock
{
    u_byte index;
    void *root;
    struct MBlock *previous;
    struct MBlock *next;
    u_short count;
    u_short usedCount;
} MBlock;

typedef struct Pool
{
    pthread_mutex_t mutex;

    u_short mblock_info[16][2];
    u_short mblock_length;

    MBlock *blocks[16];
    MBlock *reserve_blocks[16];
    u_short mblock_count[16];
} Pool;

#define POINTER_SET_INFO(pointer, index, offset) *(u_byte *)((void *)(pointer) - sizeof(u_byte)) = ((u_byte)((index) << 4) | (u_byte)(offset))

#define POINTER_GET_INDEX(pointer) ((*(u_byte *)((void *)(pointer) - sizeof(u_byte))) >> 4)
#define POINTER_GET_OFFSET(pointer) ((*(u_byte *)((void *)(pointer) - sizeof(u_byte))) & 0xF)
#define POINTER_TO_MBLOCK(info, pointer) (*(void **)((void *)(pointer) - ((info)[POINTER_GET_INDEX(pointer)][0] + sizeof(u_byte)) * POINTER_GET_OFFSET(pointer) - sizeof(void *) - sizeof(u_byte)));

#define MAX_NUMBER_OF_MBLOCK 16

void Pool_Init(Pool *self, u_short info[16][2]);
void *Pool_Malloc(Pool *self, u_int size);
void *Pool_Calloc(Pool *self, u_int size);
void *Pool_Realloc(Pool *self, void *pointer, u_int size);
void Pool_Free(Pool *self, void *p);

void Pool_Print(Pool *self);

void Delete_Pool(Pool *pool);

#endif